package tiger.parse;
import errormsg.ErrorMsg;

%%

%unicode
%cup
%char
%state COMMENT
%state STRING

%{
  	private int comment_count = 0;
	private java_cup.runtime.Symbol tok(int kind, Object value) 
	{    
		return new java_cup.runtime.Symbol(kind, yychar, yychar+yylength(), value);
	}  
  	StringBuffer string = new StringBuffer ();
	public Yylex(java.io.InputStream s, ErrorMsg e) 
	{
	  this(s);
	  errorMsg = e;
	}
	private void newline() 
	{
	  errorMsg.newline(yychar);
	}	
	private ErrorMsg errorMsg=new ErrorMsg ("???.tig");
%} 

%eofval{
{ 
	return tok(sym.EOF, null);
}
%eofval}  

NEWLINE	    =           \r|\n|\r\n
OTHERSPACE  =           [\ \t\f]
WHITESPACE  = 			{NEWLINE}|{OTHERSPACE}
LETTER	    =			[A-Za-z]
DIGIT       =			[0-9]
IDENTIFIER  = 			{LETTER}({LETTER}|{DIGIT}|_)*
INTCONST 	=			{DIGIT}{DIGIT}*
COMMENTTEXT = 			([^*/\N]|[^*\N]"/"[^*\N]|[^/\N]"*"[^/\N]|"*"[^/\N]|"/"[^*\N])*
STRING_CHAR =           [^\n\t\"\\]|"\\\^"[@A-Z\[\\\]\^_]



%%

<YYINITIAL> 
{
	{NEWLINE}			{newline();}
	{WHITESPACE}		{}
	
	"array" 			{ return tok(sym.ARRAY, null); }
	"break" 			{ return tok(sym.BREAK,null); }
	"do" 				{  return tok(sym.DO,null); }
	"else" 				{ return tok(sym.ELSE,null); }
	"end" 				{ return tok(sym.END,null); }
	"for"  				{ return tok(sym.FOR, null); }	
	"function" 			{ return tok(sym.FUNCTION,null); }
	"if"  				{ return tok(sym.IF, null); }		
	"in" 				{ return tok(sym.IN,null); }
	"let" 				{ return tok(sym.LET,null); }
	"nil" 				{ return tok(sym.NIL,null); }
	"of" 				{ return tok(sym.OF,null); }
	"then" 				{ return tok(sym.THEN,null); }
	"to" 				{ return tok(sym.TO,null); }
	"type" 				{ return tok(sym.TYPE,null); }
	"var" 				{ return tok(sym.VAR,null); }
	"while" 			{ return tok(sym.WHILE,null); }
	
	{IDENTIFIER} {return tok(sym.ID,yytext()); }
	
	{INTCONST} {
          			StringBuffer tmp = new StringBuffer(yytext());
					return tok(sym.INT, new Integer(tmp.toString()));	
				}										
		
	"+"					{ return tok (sym.PLUS, null); }
	"-"					{ return tok (sym.MINUS, null); }
	"*"					{ return tok (sym.TIMES, null); }
	"/"					{ return tok (sym.DIVIDE, null); }
	"("					{ return tok (sym.LPAREN, null); }
	")"					{ return tok (sym.RPAREN, null); }
	"["					{ return tok (sym.LBRACK, null); }
	"]"					{ return tok (sym.RBRACK, null); }
	"{"					{ return tok (sym.LBRACE, null); }
	"}"					{ return tok (sym.RBRACE, null); }
	","					{ return tok (sym.COMMA, null); }
	":"					{ return tok (sym.COLON, null); }
	";"					{ return tok (sym.SEMICOLON, null); }
	"."					{ return tok (sym.DOT, null); }
	"="					{ return tok (sym.EQ, null); }
	"<"					{ return tok (sym.LT, null); }
	">"					{ return tok (sym.GT, null); }
	">="				{ return tok (sym.GE, null); }
	"<="				{ return tok (sym.LE, null); }
	"<>"				{ return tok (sym.NEQ, null); }
	"&"					{ return tok (sym.AND, null); }
	"|"					{ return tok (sym.OR, null); }
	":="				{ return tok (sym.ASSIGN, null); }
	"/*"				{ yybegin(COMMENT); comment_count++; }
    \"					{ yybegin(STRING); string.setLength(0); }
	[^]           		{ errorMsg.error(yychar,"UNEXPECTED CHARACTER "+yytext()); }
	
}
	
<COMMENT>	
{
  "/*" 					{ comment_count++; }
  "*/" 					{ if (--comment_count == 0) yybegin(YYINITIAL); }
  {NEWLINE}				{newline();}
  {COMMENTTEXT} 		{}
  <<EOF>>        		{ errorMsg.error(yychar,"UNCLOSED COMMENT");return tok(sym.EOF, null);}
}

<STRING> 
{
		
	\"           		{ 
							yybegin(YYINITIAL); 
	                        string.toString(); 
	                        return tok(sym.STRING, string.toString());
	                    }
  \@A-Z					{ string.append(yytext().substring(1));}
  \\t                   { string.append('\t'); }
  \\n                   { string.append('\n'); }
  \\\"                  { string.append('\"'); }
  \\\\                  { string.append('\\'); }
  \\{WHITESPACE}+\\		{}
  {STRING_CHAR}+    	{ string.append( yytext()); }	
  \\{DIGIT}{3}	        { 
  							int val = Integer.parseInt(yytext().substring(1),10); 
							if (val >255)
							{
								errorMsg.error(yychar,"CONSTANT OUT OF RANGE");
							}
							else
							{	
								string.append((char)val);
							}
						}
	\\[^]              	{ errorMsg.error(yychar,"UNEXPECTED CHARACTER"+yytext()); }
	{NEWLINE}		    { errorMsg.error(yychar,"'\"' EXPECTED"); yybegin(YYINITIAL);}
	<<EOF>>             { errorMsg.error(yychar,"'\"' EXPECTED"); return tok(sym.EOF, null); }
}